From 69f457426ae2a7b1e2cb8e74034a636831aae079 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Tue, 18 Sep 2012 09:31:17 -0400 Subject: [PATCH] Switch to an extended form of _NET_WM_SYNC_REQUEST_COUNTER By exporting two XSync counters on a toplevel window, we subscribe to an extended form of the _NET_WM_SYNC_REQUEST_COUNTER protocol, where the window manager can initiate an atomic frame, as previously, but the application can also do so by incrementing the new counter to an odd value, and then to an even value to finish the frame. See: https://mail.gnome.org/archives/wm-spec-list/2011-October/msg00006.html The support for 64-bit integers that GLib requires is used to simplify the logic. https://bugzilla.gnome.org/show_bug.cgi?id=685460 --- gdk/x11/gdkdisplay-x11.c | 10 ++++----- gdk/x11/gdkwindow-x11.c | 45 +++++++++++++++++++++++++++++++--------- gdk/x11/gdkwindow-x11.h | 12 ++++++----- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 20bde58a80..5af36d278f 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -747,10 +747,10 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, } #ifdef HAVE_XSYNC - if (!is_substructure && toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value)) + if (!is_substructure && toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0) { - toplevel->current_counter_value = toplevel->pending_counter_value; - XSyncIntToValue (&toplevel->pending_counter_value, 0); + toplevel->configure_counter_value = toplevel->pending_counter_value; + toplevel->pending_counter_value = 0; } #endif @@ -1126,9 +1126,7 @@ _gdk_wm_protocols_filter (GdkXEvent *xev, if (toplevel) { #ifdef HAVE_XSYNC - XSyncIntsToValue (&toplevel->pending_counter_value, - xevent->xclient.data.l[2], - xevent->xclient.data.l[3]); + toplevel->pending_counter_value = xevent->xclient.data.l[2] + ((gint64)xevent->xclient.data.l[3] << 32); #endif } return GDK_FILTER_REMOVE; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index e86a73322c..6b8a0e8fab 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -200,6 +200,19 @@ _gdk_x11_window_update_size (GdkWindowImplX11 *impl) } } +static void +set_sync_counter(Display *display, + XSyncCounter counter, + gint64 value) +{ + XSyncValue sync_value; + + XSyncIntsToValue(&sync_value, + value & G_GINT64_CONSTANT(0xFFFFFFFF), + value >> 32); + XSyncSetCounter(display, counter, sync_value); +} + /***************************************************** * X11 specific implementations of generic functions * *****************************************************/ @@ -612,20 +625,24 @@ ensure_sync_counter (GdkWindow *window) Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); XSyncValue value; Atom atom; + XID counters[2]; XSyncIntToValue (&value, 0); toplevel->update_counter = XSyncCreateCounter (xdisplay, value); + toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value); atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST_COUNTER"); - + + counters[0] = toplevel->update_counter; + counters[1] = toplevel->extended_update_counter; XChangeProperty (xdisplay, GDK_WINDOW_XID (window), atom, XA_CARDINAL, 32, PropModeReplace, - (guchar *)&toplevel->update_counter, 1); + (guchar *)counters, 2); - XSyncIntToValue (&toplevel->current_counter_value, 0); + toplevel->current_counter_value = 0; } } #endif @@ -1006,7 +1023,7 @@ gdk_toplevel_x11_free_contents (GdkDisplay *display, toplevel->update_counter); toplevel->update_counter = None; - XSyncIntToValue (&toplevel->current_counter_value, 0); + toplevel->current_counter_value = 0; } #endif } @@ -4863,13 +4880,21 @@ gdk_x11_window_configure_finished (GdkWindow *window) if (toplevel && toplevel->update_counter != None && GDK_X11_DISPLAY (display)->use_sync && - !XSyncValueIsZero (toplevel->current_counter_value)) + toplevel->configure_counter_value != 0) { - XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), - toplevel->update_counter, - toplevel->current_counter_value); - - XSyncIntToValue (&toplevel->current_counter_value, 0); + set_sync_counter (GDK_WINDOW_XDISPLAY (window), + toplevel->update_counter, + toplevel->configure_counter_value); + + toplevel->current_counter_value = toplevel->configure_counter_value; + if ((toplevel->current_counter_value % 2) == 1) + toplevel->current_counter_value += 1; + + toplevel->configure_counter_value = 0; + + set_sync_counter (GDK_WINDOW_XDISPLAY (window), + toplevel->extended_update_counter, + toplevel->current_counter_value); } } #endif diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 3dde77767d..b4b737604b 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -144,11 +144,13 @@ struct _GdkToplevelX11 #ifdef HAVE_XSYNC XID update_counter; - XSyncValue pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */ - XSyncValue current_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received - * where we have also seen the corresponding - * ConfigureNotify - */ + XID extended_update_counter; + gint64 pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */ + gint64 configure_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received + * where we have also seen the corresponding + * ConfigureNotify + */ + gint64 current_counter_value; #endif }; -- 2.30.2